home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1994…tember: Reference Library / Dev.CD Sep 94.toast / Periodicals / develop / develop Issue 19 / develop 19 code / Truffles Sample / graphics shell.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-05-24  |  12.0 KB  |  372 lines  |  [TEXT/KAHL]

  1. /**  
  2.  --        graphics shell.c
  3.  --
  4.  --        This file is a shell that can be used to build QuickDraw GX graphics applications.  
  5.  --        It contains all of the required calls to use the "new" QuickDraw GX routines and 
  6.  --        QuickDraw (i.e. windows) together. It will put up one window. You "quit" 
  7.  --        the application by clicking in the close box.  This shell does not use a menu.
  8.  --        
  9.  --     The application is expected to supply the following functions which are called
  10.  --        by this shell:
  11.  --
  12.  --            void DoInitialization(WindowPtr);
  13.  --            void DoDraw(WindowPtr);
  14.  --            void DoDispose(WindowPtr);
  15.  --            void DoClick(gxPoint, WindowPtr);
  16.  --            void DoIdle(WindowPtr);
  17.  --
  18.  --
  19.  --     Change History:         
  20.  --
  21.  --        4/94    - Added the gxPoint as a parameter to the DoClick( gxPoint mouseLoc, WindowPtr myWindow ) 
  22.  --                  function to support hit testing.  PLA
  23.  --
  24.  --        3/94    - Removed the following varaibles: gDebugging & gGiveMeValidation see the comments
  25.  --                  for details (below). 
  26.  --
  27.  --                - Added a Gestalt check to see if GX has been installed. Added extensive error 
  28.  --                  checking to make sure the GX graphics client has been created and the GX heap
  29.  --                  correctly allocated. This shell will shut down at start-up and alert the user
  30.  --                  to the problem and bail if: GX is not installed, we cannot create the graphics
  31.  --                  client, or create a GX heap.  PLA
  32.  --
  33.  --        12/93    Updated the comment above the GXNewGraphicsCLient call to reflect the new fucntionality
  34.  --                of this call in ß3. I also removed the work around with GXConvertQDPoint (..) where
  35.  --                the call would not survive validation under ß2. Under ß3 the call suceeds when validation
  36.  --                is set.   PLA
  37.  --
  38.  --        8/93    - Updated this file to run with the QD GX ß2 "GX-ified" interfaces
  39.  --                - worked around a problem with GXConvertQDPoint (..) see the comments within
  40.  --                  the GetWindowBoundsShape (..) call for details (below).  PLA
  41.  --
  42.  --        6/92    Made the following variables global: gDebugging, gGiveMeValidation,gGraphicsHeapSize. 
  43.  --                See the comments for detail in this file.  PLA
  44.  --
  45.  --        6/91    Updated the shell to reflect the changes in "Graphics" v1.0d21.2.  PLA
  46.  --
  47.  --        3/90    New  - PLA
  48.  --
  49.  --
  50.  --        © Apple Computer, Inc. 1990 - 1994  All rights reserved
  51.  --                                
  52. **/
  53.  
  54. #include <Desk.h>
  55. #include <Events.h>
  56. #include <Fonts.h>
  57. #include <Windows.h>
  58. #include <Memory.h>
  59. #include <ToolUtils.h>
  60. #include <Quickdraw.h>
  61. #include <GestaltEqu.h>
  62.  
  63. #include "graphics toolbox.h"
  64. #include "graphics routines.h"
  65. #include "graphics macintosh.h"
  66. #include "graphics libraries.h"
  67. #include "graphics debugging.h"
  68.  
  69. #include "graphics shell.h"
  70.  
  71. #define    kOSEvent                        app4Evt    // event used by MultiFinder
  72. #define    kSuspendResumeMessage            1        // high byte of suspend/resume event message
  73. #define    kResumeMask                        1        // bit of message field for resume vs. suspend
  74.  
  75.  
  76. #if defined(powerc) || defined(__powerc)
  77.     QDGlobals    qd;
  78. #endif
  79.  
  80.  
  81. WindowPtr         gWindow, whichWindow;
  82.  
  83. EventRecord        gtheEvent;
  84. gxShape         gWindowBoundsShape;
  85. gxViewPort        gTheWindowsViewPort;    
  86.  
  87. /**------ Function Prototypes -----**/
  88. void main(void);
  89. gxShape GetWindowBoundsShape(void);
  90. Boolean EventLoop(void);
  91. void SetUpGXDebuggingWorld (Boolean GXDebuggingInstalled);
  92.  
  93. /*------ main -----------------------------------------------------------------------------------------*/
  94.  
  95. void main()
  96. {        
  97.     CursHandle            theCurs; 
  98.     long                theFeature;
  99.     Boolean                debuggingInitInstalled = false;
  100.     
  101.     //
  102.     //   Generic heap initialization.
  103.     //
  104.     MaxApplZone(); 
  105.     MoreMasters(); MoreMasters(); MoreMasters(); 
  106.     MoreMasters(); MoreMasters(); MoreMasters(); 
  107.  
  108.     //
  109.     //   Initialize the toolbox 
  110.     //
  111.      InitGraf(&qd.thePort);
  112.     InitFonts();
  113.     InitWindows();
  114.     InitCursor();
  115.  
  116.     theCurs = GetCursor(watchCursor);
  117.     SetCursor(*theCurs);
  118.  
  119.     //
  120.     //    Check to see if QuickDraw GX is installed. If not, alert the user...
  121.     //
  122.     if ( (Gestalt(gestaltGraphicsVersion, &theFeature) == noErr) )
  123.     {
  124.         gxGraphicsClient     newClient;
  125.         
  126.         //
  127.         //    The GX gestaltGraphicsAttr Gestalt attribute can be used to determine if:
  128.         //    the graphics piece of GX has been loaded, the GX debugging init is installed, or
  129.         //    your are running the PowerPC version. 
  130.         //
  131.         //    In our case, we only need to know if the debugging init was installed. If it is,
  132.         //    we will enable the GX validation and notice handling features.We define 
  133.         //    debuggingInitInstalled as true to enable GX validation and notice handler
  134.         //  within the SetUpGXDebuggingWorld function.
  135.         //
  136.         if ( (Gestalt(gestaltGraphicsAttr, &theFeature) == noErr) )
  137.           if ( (theFeature & gestaltGraphicsIsDebugging) == gestaltGraphicsIsDebugging ) 
  138.              debuggingInitInstalled = true;
  139.     
  140.  
  141.         newClient = GXNewGraphicsClient(nil, gGraphicsHeapSize * 1024, 0L);
  142.  
  143.         //
  144.         //    After we attempted to create the graphics client, we need to determine if the call
  145.         //  succeeded. If the call did not (as in the case for all GX functions), "newClient" will
  146.         //    be nil. If it is, we alert the user to the problem. Otherwise, we will attempted to 
  147.         //    allocate the GX heap below...
  148.         //        
  149.         if ( newClient ) 
  150.         {
  151.             //
  152.             //    Initialize the new graphics environment and create the GX heap.
  153.             //
  154.             GXEnterGraphics();
  155.  
  156.             //
  157.             //    Calling GXEnterGraphics allocates the memory within the GX heap. The only reason the
  158.             //  call would not succeed is if there is not enough memory. In this case, the graphics 
  159.             //  error which will be posted is -27999 (out of memory). At this point, we have not 
  160.             //    installed an error handler, so we check for the error number corresponding to the 
  161.             //  out of memory error.
  162.             //
  163.             if ( GXGetGraphicsError( nil ) != -27999 ) 
  164.             {
  165.                 SetUpGXDebuggingWorld (debuggingInitInstalled);
  166.  
  167.                 //
  168.                 //    Create a window and attach a GX viewPort to it. By attaching the viewPort to 
  169.                 //    the window will make sure that when a user moves or resizes the window all of
  170.                 //    the GX drawing will occur within window. 
  171.                 //
  172.                 //    By the way, you cannot directly manipulate the parent viewPort attached to the
  173.                 //    window, you will recieve a graphics error. This viewPort can only be manipulated
  174.                 //  by the GX system. If you want to manipulate a viewPort attached to a window, it
  175.                 //     _must_ be a child viewPort attached to the the parent viewPort attached to the
  176.                 //    window.
  177.                 //
  178.                 gWindow = NewWindow(nil, &gWindowQDRect, gWindowTitle, true, noGrowDocProc,
  179.                                    (WindowPtr)-1L, true, 0L);
  180.                                    
  181.                 gTheWindowsViewPort = GXNewWindowViewPort(gWindow);
  182.  
  183.                 GXIgnoreGraphicsNotice(transform_already_set);
  184.                 SetDefaultViewPort(gTheWindowsViewPort);
  185.                 GXPopGraphicsNotice();
  186.  
  187.                 //
  188.                 //  Get the global bounds of the window.
  189.                 //
  190.                 gWindowBoundsShape = GetWindowBoundsShape();
  191.  
  192.                  //
  193.                  //    Create the GX shapes we are going to draw to the window. 
  194.                  //
  195.                  DoInitialization(gWindow);
  196.  
  197.                 SetCursor(&qd.arrow);  
  198.     
  199.                 while (EventLoop())
  200.                       DoIdle(gWindow);   // loop until the window is closed
  201.  
  202.                 DoDispose(gWindow);
  203.     
  204.                 GXExitGraphics();     // Deallocate all of the default structures
  205.                 GXDisposeGraphicsClient(newClient);
  206.         
  207.             } else {
  208.                 //
  209.                 //     Since, we can not allocate the requested size for our GX heap, we need to throw
  210.                 //  away the client we created and alert the user that there is not enough memory to
  211.                 //  continue.
  212.                 //
  213.                 //    However, you could try to create a smaller GX heap. If you decide to try to create
  214.                 //     a smaller GX heap which would meet the needs of your application, you need to 
  215.                 //     dispose of the client you had originally created. Why? The original client 
  216.                 //    contains the GX heap size requested, which was too big, therefore you need to 
  217.                 //    dispose of it and create a client requesting a smaller size and call GXEnterGraphics
  218.                 //     and check for an error. 
  219.                 //
  220.                 GXDisposeGraphicsClient( newClient );
  221.                 DebugStr ("\p Unfortunately, there is not enough memory for GX, please quit an app...");
  222.             }
  223.           }
  224.  
  225.     } else DebugStr ("\p Unfortunately, you have not installed QuickDraw GX, I can't run without GX...");
  226.     
  227. }
  228.  
  229.  
  230.  
  231. /*------ SetUpGXDebuggingWorld ------------------------------------------------------------------------*/
  232. //
  233. //    This function enables the GX error handling capabilities and validation routines. The validation
  234. //    routines are only enabled, if the user has installed the QuickDraw GX debugging init. These routines
  235. //    are not available with the non-debugging init. Calling them when they are not installed will not 
  236. //    cause any problems, but it will cause unnecessary work to be done by your application and the GX 
  237. //    dispatcher.
  238. //
  239. void SetUpGXDebuggingWorld (Boolean debuggingInitInstalled)
  240. {
  241.       // 
  242.     //    We set-up GX validation, if the user has installed the "GXGraphics (debug)" init (formerly
  243.     //    named "aSecretGraphics.debug). This validation setting is the reccommended setting while
  244.     //    you are developing your GX application. As you increase the amount of validation, the drawing
  245.     //    speed will SLOW down due to all of the internal checking. 
  246.     //
  247.     //    For additional details regarding the various levels of validation, please see the
  248.     //    QuickDraw GX : Environment & Utilities book.
  249.     //
  250.     if ( debuggingInitInstalled ) GXSetValidation(gxPublicValidation + gxTypeValidation); 
  251.  
  252.     // 
  253.     //    Calling SetGraphicsLibraryErrors will install a GX error and warning handler. This
  254.     //    call is provided by the QuickDraw GX "graphics debugging library". Any time a GX error
  255.     //    or warning is generated, it will be posted to Macsbug.
  256.     //
  257.     SetGraphicsLibraryErrors ();
  258.         
  259.     //
  260.     //    If the user has installed the GX debugging version, we install a notice handler. Why? The
  261.     //    GX notice handling capabilities are only available with the debugging version.
  262.     //
  263.     if ( debuggingInitInstalled ) SetGraphicsLibraryNotices();
  264. }
  265.  
  266.  
  267.  
  268. /*------ GetWindowBoundsShape -------------------------------------------------------------------------*/
  269.  
  270. gxShape  GetWindowBoundsShape()
  271. {
  272.     Rect                theRect;
  273.     Point                QDtopLeft;
  274.     Point                QDbotRight;
  275.     gxPoint                QDGXtopLeft;
  276.     gxPoint                QDGXbotRight;
  277.     gxRectangle            theQDGXRect;
  278.     
  279.     //
  280.     // The QuickDraw rect and points which represent the portRect of the window. 
  281.     //
  282.     theRect = gWindow->portRect;
  283.     QDtopLeft.h = theRect.left;
  284.     QDtopLeft.v = theRect.top;
  285.     QDbotRight.h = theRect.right;
  286.     QDbotRight.v = theRect.bottom;
  287.      
  288.     //
  289.     //  Convert the global Quickdraw coordinates to local fixed coordinates.
  290.     //
  291.     GXConvertQDPoint(&QDtopLeft, 0, &QDGXtopLeft);
  292.     GXConvertQDPoint(&QDbotRight, 0, &QDGXbotRight);
  293.  
  294.     //
  295.     //  Setup the dimensions for "gWindowBoundsShape"
  296.     //
  297.     theQDGXRect.top = QDGXtopLeft.y;
  298.     theQDGXRect.left = QDGXtopLeft.x;
  299.     theQDGXRect.bottom = QDGXbotRight.y;
  300.     theQDGXRect.right = QDGXbotRight.x;
  301.     
  302.     return (GXNewRectangle(&theQDGXRect));
  303. }
  304.  
  305.  
  306.  
  307. /*------ EventLoop ------------------------------------------------------------------------------------*/
  308.  
  309. Boolean EventLoop()
  310. {
  311.     static long     sleep = 0;
  312.  
  313.     WaitNextEvent(everyEvent, >heEvent, sleep, nil);
  314.          
  315.     switch(gtheEvent.what)
  316.     {                    
  317.         case updateEvt:
  318.                 BeginUpdate((WindowPtr) gtheEvent.message);
  319.                 SetPort(gWindow);
  320.                 DoDraw(gWindow);
  321.                 EndUpdate((WindowPtr) gtheEvent.message);
  322.         break;
  323.         
  324.         case mouseDown:
  325.             switch (FindWindow(gtheEvent.where, &whichWindow)) {
  326.                 case inSysWindow:
  327.                     SystemClick(>heEvent, whichWindow);
  328.                 break;
  329.                         
  330.                 case inDrag:
  331.                     DragWindow(whichWindow, gtheEvent.where, &qd.screenBits.bounds);
  332.                 break;
  333.  
  334.                 case inGoAway:
  335.                     if (TrackGoAway(whichWindow, gtheEvent.where))
  336.                         return false;
  337.                 break;
  338.                 
  339.                 case inContent:
  340.                     if (whichWindow != FrontWindow())
  341.                          SelectWindow(whichWindow);
  342.                      else
  343.                      {
  344.                          gxPoint        mouseLoc;
  345.                          Point        currMouseLoc;
  346.                          
  347.                          currMouseLoc.h = gtheEvent.where.h;
  348.                          currMouseLoc.v = gtheEvent.where.v;
  349.                          
  350.                         GXConvertQDPoint(&currMouseLoc, gTheWindowsViewPort, &mouseLoc);
  351.  
  352.                          DoClick(mouseLoc, gWindow);
  353.                      }
  354.                 break;
  355.  
  356.             }
  357.             
  358.         case kOSEvent:
  359.             switch ((unsigned long) gtheEvent.message >> 24) {    //  high byte of message
  360.                  case kSuspendResumeMessage:            //  suspend/resume is also an activate/deactivate
  361.                     if ((gtheEvent.message & kResumeMask) == 0)
  362.                        sleep = 80;                    // we are headed to the background, so slow down...  
  363.                     else
  364.                        sleep = 0;                    // we are headed to the foreground, so speed up... 
  365.                 break;
  366.             }
  367.                 break;
  368.     }
  369.     return true;
  370. }
  371.  
  372.